/**
 * TerrainPalette.java 2005. 6. 22.
 *
 * @copyrights 2004 PSIA Corp. All rights are reserved.
 */
package cs348a.color;

/**
 * A <code>TerrainPalette</code> defines a terrain-like color palette.
 *
 * @author Taeksoo Jung, YoungJin Kim
 */
public final class TerrainPalette extends BasicPalette {
	/** Limit of the first term */
	private static final int TERM_LIMIT1 = (int) (SIZE * 0.1);
	
	/** Limit of the second term */
	private static final int TERM_LIMIT2 = (int) (SIZE * 0.15);
	
	/** Limit of the third term */
	private static final int TERM_LIMIT3 = (int) (SIZE * 0.4);
	
	/** Limit of the forth term */
	private static final int TERM_LIMIT4 = (int) (SIZE * 0.6);

	/** Singleton instance */
	public static final TerrainPalette INSTANCE = getInstance();

	/**
	 * Constructor for <code>TerrainPalette</code>.
	 * 
	 * @param reds array of red components
	 * @param greens array of green components
	 * @param blues array of blue components
	 */
	private TerrainPalette(byte[] reds, byte[] greens, byte[] blues) {
		super("Terrain", reds, greens, blues);
	}
	
	/**
	 * Returns the singleton instance.
	 * 
	 * @return the singleton instance
	 */
	private static TerrainPalette getInstance() {
		// Creates arrays of components.
		byte[] reds = new byte[SIZE];
		byte[] greens = new byte[SIZE];
		byte[] blues = new byte[SIZE];
		
		// Creates the first term of the components.
		for (int i = 0; i < TERM_LIMIT1; i++) {
			// Sets the red component.
			double f = (-2.0 * i + 0.2 * SIZE);
			reds[i] = cutOff(f);

			// Sets the green component.
			f = (4.0 * i + 0.2 * SIZE);
			greens[i] = cutOff(f);

			// Sets the blue component.
			f = (4.0 * i + 0.6 * SIZE);
			blues[i] = cutOff(f);		
		}

		// Creates the second term of the components.
		for (int i = TERM_LIMIT1; i < TERM_LIMIT2; i++) {
			// Sets the red component.
			double f = 0;
			reds[i] = cutOff(f);

			// Sets the green component.
			f = (4.0 * i + 0.2 * SIZE);
			greens[i] = cutOff(f);

			// Sets the blue component.
			f = (12.0 * i + 2.2 * SIZE);
			blues[i] = cutOff(f);
		}
		
		// Creates the third term of the components.
		for (int i = TERM_LIMIT2; i < TERM_LIMIT3; i++) {
			// Sets the red component.
			double f = (4.0 * i - 0.6 * SIZE);
			reds[i] = cutOff(f); 

			// Sets the green component.
			f = (0.8 * i + 0.68 * SIZE);
			greens[i] = cutOff(f);

			// Sets the blue component.
			f = (0.8 * i + 0.28 * SIZE);
			blues[i] = cutOff(f);
		}

		// Forth term.
		for (int i = TERM_LIMIT3; i < TERM_LIMIT4; i++) {
			// Sets the red component.
			double f = (-2.5 * i + 2.0 * SIZE);
			reds[i] = cutOff(f);

			// Sets the green component.
			f = (-3.2 * i + 2.28 * SIZE);
			greens[i] = cutOff(f);

			// Sets the blue component.
			f = (-1.5 * i + 1.2 * SIZE);
			blues[i] = cutOff(f);
		}
		
		// Fifth term.
		for (int i = TERM_LIMIT4; i < SIZE; i++) {
			// Sets the red component.
			double f = (1.25 * i - 0.25 * SIZE);
			reds[i] = cutOff(f);

			// Sets the green component.
			f = (1.6 * i - 0.6 * SIZE);
			greens[i] = cutOff(f);

			// Sets the blue component.
			f = (1.75 * i - 0.75 * SIZE);
			blues[i] = cutOff(f);
		}
		
		return new TerrainPalette(reds, greens, blues);
	}
}
